package com.mate.cloud.auth.config;

import com.mate.cloud.auth.filter.JwtFilter;
import com.mate.cloud.auth.service.UserService;
import com.mate.cloud.auth.service.impl.CustomUserDetailsService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import javax.sql.DataSource;

/**
 * Spring Security 配置类
 *
 * @author: MI
 * @email: 448341911@qq.com
 * @createTime: 2024/6/14 18:11
 * @updateUser: MI
 * @updateTime: 2024/6/14 18:11
 * @updateRemark: 修改内容
 * @version: v1.0
 */
@Slf4j
@Configuration
@EnableWebSecurity
public class AuthorizationServerConfig {

    @Resource
    private DataSource dataSource;

    @Resource
    JwtFilter jwtFilter;//后面jwt验证需要用到的过滤器，现在先不理它

    @Resource
    private UserDetailsService userDetailsService;
    //滤器链的相关设置
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        log.info("securityFilterChain()");
        // csrfCustomizer.ignoringRequestMatchers(*) 表示所有请求地址都不使用 csrf
        http.csrf(AbstractHttpConfigurer::disable)//禁用csrf保护，前后端分离不需要
                .authorizeHttpRequests(authorize -> authorize
                        .requestMatchers(HttpMethod.POST, "/user/login", "/user/register").permitAll()
                        .anyRequest().authenticated()
                )
                //取消默认登录页面的使用
                .formLogin(AbstractHttpConfigurer::disable)
                //取消默认登出页面的使用
                .logout(AbstractHttpConfigurer::disable)
                //将自己配置的PasswordEncoder放入SecurityFilterChain中
                .authenticationProvider(authenticationProvider())
                //禁用session，因为我们已经使用了JWT
                .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                .httpBasic(AbstractHttpConfigurer::disable)//禁用httpBasic，因为我们传输数据用的是post，而且请求体是JSON
                //开放两个接口，一个注册，一个登录，其余均要身份认证
                .addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class)//将用户授权时用到的JWT校验过滤器添加进SecurityFilterChain中，并放在UsernamePasswordAuthenticationFilter的前面
                // remember me
                .rememberMe(rememberMeCustomizer -> rememberMeCustomizer
                        .userDetailsService(userDetailsService) //登录逻辑交给哪个对象
                        //持久层对象
                        .tokenRepository(getPersistentTokenRepository())
                        // 单位秒
                        .tokenValiditySeconds(120)
                );

        return http.build();
    }


    /**
     * 处理身份验证
     */
    @Bean
    public AuthenticationProvider authenticationProvider(){
        DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
        provider.setPasswordEncoder(passwordEncoder());
        provider.setUserDetailsService(userDetailsService);
        return provider;
    }


    // 持久化对象
    @Bean
    public PersistentTokenRepository getPersistentTokenRepository() {
        JdbcTokenRepositoryImpl jdbcTokenRepositoryImpl = new JdbcTokenRepositoryImpl();
        jdbcTokenRepositoryImpl.setDataSource(dataSource);
        // 自动建表，第一次启动时需要，第二次启动时注释掉
        jdbcTokenRepositoryImpl.setCreateTableOnStartup(false);
        return jdbcTokenRepositoryImpl;
    }


    // 配置密码编码器
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    /**
     * 身份验证管理器
     */
    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) throws Exception {
        return configuration.getAuthenticationManager();
    }
}
